package com.liaoyifan.core.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.liaoyifan.core.constant.Constants;
import com.liaoyifan.core.constant.Properties;
import com.liaoyifan.core.enums.PoolNameEnum;
import com.liaoyifan.core.opera.CoreEnumConverterFactory;
import com.liaoyifan.core.thread.PoolConfig;
import com.liaoyifan.core.thread.ThreadPool;
import com.liaoyifan.core.util.Json;
import com.liaoyifan.core.util.RequestContext;
import com.liaoyifan.core.util.SpringContext;
import com.liaoyifan.core.valid.Message;
import com.liaoyifan.core.valid.Validation;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.CacheControl;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.resource.VersionResourceResolver;

@SuppressWarnings({"SameReturnValue", "unused"})
@Configuration
@Import(SpringContext.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnProperty(name = Properties.WEB_MVC_ENABLE, havingValue = Constants.TRUE)
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Bean("objectMapper")
    public ObjectMapper objectMapper() {
        return Json.OBJECT_MAPPER;
    }

    @Bean("messageSource")
    @Primary
    public MessageSource messageSource() {
        return Message.MESSAGE_SOURCE;
    }

    @Bean("localeResolver")
    @Primary
    public LocaleResolver localeResolver() {
        return RequestContext.LOCALE_RESOLVER;
    }

    @Bean("defaultValidator")
    @Primary
    public LocalValidatorFactoryBean defaultValidator() {
        return Validation.FAST_VALIDATOR;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**")
                .addResourceLocations(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "/static/")
                .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS).cachePublic())
                .resourceChain(true)
                .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
    }

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverterFactory(new CoreEnumConverterFactory());
    }

    @Override
    public Validator getValidator() {
        return defaultValidator();
    }

    @Bean
    public Executor taskExecutor() {
        return ThreadPool.get(PoolConfig.get(PoolNameEnum.SPRING_ASYNC.getValue()));
    }
}
